/**
 * 
 */
package org.t2.simulator;

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

import org.gaming.protobuf3.simulator.SimulatorMain;
import org.gaming.protobuf3.simulator.netty.NettyHandler;
import org.gaming.protobuf3.simulator.plugin.PluginLogic;
import org.gaming.protobuf3.simulator.protocol.ProtocolMessage;
import org.gaming.protobuf3.simulator.protocol.parser.ProtocolType;
import org.gaming.simulator.simulator.view.SimulatorView;

import com.google.protobuf.AbstractMessage;
import com.google.protobuf.InvalidProtocolBufferException;

import pb.t2.protobuf.Wrapper.MessageWrapper;
import pb.t2.protobuf.player.Player.HeartBeatRequest;
import pb.t2.protobuf.player.Player.PbLoginStatus;
import pb.t2.protobuf.player.Player.PlayerLoginRequest;
import pb.t2.protobuf.player.Player.PlayerLoginResponse;

/**
 * @auther YY
 */
public class T2Logic implements PluginLogic {

	private AtomicInteger idGen = new AtomicInteger(0);
	
	@Override
	public AbstractMessage login(String openId, int areaId) {
		for(int i = 0; i < 10; i++) {
			Boolean handshake = SimulatorMain.NETTY.getChannel().attr(NettyHandler.HANDSHAKE).get();
			if(handshake == null) {
				try {
					Thread.sleep(20);
					System.out.println("HANDSHAKE");
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			} else {
				break;
			}
		}
		
		PlayerLoginRequest.Builder builder = PlayerLoginRequest.newBuilder();
		builder.setOpenId(openId);
		builder.setServerId(areaId);
		builder.setChannelId(2);
		return builder.build();
	}

	@Override
	public AbstractMessage create(String openId, int areaId) {
		PlayerLoginRequest.Builder builder = PlayerLoginRequest.newBuilder();
		builder.setOpenId(openId);
		builder.setServerId(areaId);
		return builder.build();
	}

	@Override
	public int getProtocolId(String protocolName) {
		Integer cmd = ProtoFileReader.reqProtocolIdMap.get(protocolName);
		if(cmd != null) {
			return cmd;
		}
		cmd = ProtoFileReader.resProtocolIdMap.get(protocolName);
		if(cmd != null) {
			return cmd;
		}
		return 0;
	}

	@Override
	public ProtocolType getProtocolType(String protocolName) {
		if(ProtoFileReader.resProtocolIdMap.containsKey(protocolName)) {
			return ProtocolType.RESPONSE;
		} else {
			return ProtocolType.REQUEST;
		}
	}

	@Override
	public ProtocolMessage encode(String protocolName, AbstractMessage msg) {
		Integer cmd = ProtoFileReader.reqProtocolIdMap.get(protocolName);
		if(cmd == null) {
			return null;
		}
		
		MessageWrapper.Builder builder = MessageWrapper.newBuilder();
		builder.setId(idGen.incrementAndGet());
		builder.setProtoId(cmd);
		builder.setData(msg.toByteString());
		MessageWrapper wrapper = builder.build();
		
		ProtocolMessage message = new ProtocolMessage();
		message.setProtocolId(wrapper.getProtoId());
		message.setContent(wrapper.toByteArray());
		message.setMessageId(wrapper.getId());
		return message;
	}

	@Override
	public ProtocolMessage decode(byte[] data) {
		try {
			MessageWrapper wrapper = MessageWrapper.parseFrom(data);
			ProtocolMessage message = new ProtocolMessage();
			message.setMessageId(wrapper.getId());
			message.setProtocolId(wrapper.getProtoId());
			message.setContent(wrapper.getData().toByteArray());
			return message;
		} catch (InvalidProtocolBufferException e) {
			e.printStackTrace();
		}
		return null;
	}

	@Override
	public void onDisconnect() {
		//停止心跳定时器
		if(scheduledFuture != null && !scheduledFuture.isCancelled()) {
			scheduledFuture.cancel(false);
		}
	}

	@Override
	public void onConnect() {
	}

	private ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
	private ScheduledFuture<?> scheduledFuture = null;
			
	@Override
	public void onRead(AbstractMessage object) {
		if(object instanceof PlayerLoginResponse) {
			PlayerLoginResponse response = (PlayerLoginResponse)object;
			SimulatorView simulatorView = SimulatorView.instance();
			simulatorView.setSubTitle("    玩家：" + response.getPlayer().getId() + " - " + response.getPlayer().getNick());
			
			if(response.getLoginStatus() == PbLoginStatus.NORMAL) {
				if(scheduledFuture != null && !scheduledFuture.isCancelled()) {
					scheduledFuture.cancel(false);
				}
				//开启心跳定时器
				scheduledFuture = executorService.scheduleAtFixedRate(new Runnable() {
					
					@Override
					public void run() {
						MessageWrapper.Builder builder = MessageWrapper.newBuilder();
						builder.setProtoId(HeartBeatRequest.Proto.ID_VALUE);
						builder.setData(HeartBeatRequest.getDefaultInstance().toByteString());
						MessageWrapper wrapper = builder.build();
						SimulatorMain.NETTY.write(wrapper.toByteArray());
					}
				}, 0, 30, TimeUnit.SECONDS);
			}
		}
	}
	
}
